#include "stdafx.h"
#include "gp_Pnt2d.h"
#include "gp_Dir2d.h"
#include "gp_Ax2d.h"
#include "gp_Trsf2d.h"
#include "gp_Vec2d.h"
#include "gp_Ax22d.h"
#include "gp_XY.h"

 gp_Ax22d::gp_Ax22d() : vydir(0.,1.), vxdir(1.,0.)
{}

 gp_Ax22d::gp_Ax22d(const gp_Pnt2d& P , 
			  const gp_Dir2d& Vx, 
			  const gp_Dir2d& Vy) : 
			  point(P), 
			  vydir(Vy), 
			  vxdir(Vx)
{
  double value = Vx.Crossed(Vy);
  if (value >= 0.0) vydir.SetCoord(-vxdir.Y(), vxdir.X());
  else              vydir.SetCoord( vxdir.Y(),-vxdir.X());
}

 gp_Ax22d::gp_Ax22d(const gp_Pnt2d&        P    , 
			  const gp_Dir2d&        Vx   , 
			  const bool Sense) : 
			  point(P), 
			  vxdir(Vx)
{
  if (Sense) vydir.SetCoord(-Vx.Y(), Vx.X());
  else       vydir.SetCoord( Vx.Y(),-Vx.X());
}

 gp_Ax22d::gp_Ax22d(const gp_Ax2d&         A   , 
			  const bool Sense) : 
			  point(A.Location()), 
			  vxdir(A.Direction())
{
  if (Sense) vydir.SetCoord(-vxdir.Y(), vxdir.X());
  else       vydir.SetCoord( vxdir.Y(),-vxdir.X());
}

 void gp_Ax22d::SetAxis(const gp_Ax22d&  A1)
{
  point = A1.Location();
  vxdir = A1.XDirection();
  vydir = A1.YDirection();
}

 void gp_Ax22d::SetXAxis (const gp_Ax2d&  A1)
{
  bool sign = (vxdir.Crossed(vydir)) >= 0.0;
  point = A1.Location ();
  vxdir = A1.Direction();
  if (sign) vydir.SetCoord(-vxdir.Y(), vxdir.X());
  else      vydir.SetCoord( vxdir.Y(),-vxdir.X());
}

 void gp_Ax22d::SetYAxis (const gp_Ax2d&  A1)
{
  bool sign = (vxdir.Crossed(vydir)) >= 0.0;
  point = A1.Location ();
  vydir = A1.Direction();
  if (sign) vxdir.SetCoord( vydir.Y(),-vydir.X());
  else      vxdir.SetCoord(-vydir.Y(), vydir.X());
}

 void gp_Ax22d::SetLocation (const gp_Pnt2d& P)
{ point = P; }

 void gp_Ax22d::SetXDirection (const gp_Dir2d&  Vx)
{ 
  bool sign = (vxdir.Crossed(vydir)) >= 0.0;
  vxdir = Vx;
  if (sign) vydir.SetCoord(-Vx.Y(), Vx.X());
  else      vydir.SetCoord( Vx.Y(),-Vx.X());
}

 void gp_Ax22d::SetYDirection (const gp_Dir2d& Vy)
{
  bool sign = (vxdir.Crossed(vydir)) >= 0.0;
  vydir = Vy;
  if (sign) vxdir.SetCoord( Vy.Y(),-Vy.X());
  else      vxdir.SetCoord(-Vy.Y(), Vy.X());
}

 gp_Ax2d gp_Ax22d::XAxis () const
{  return gp_Ax2d(point, vxdir); }

 gp_Ax2d gp_Ax22d::YAxis () const
{  return gp_Ax2d(point, vydir); }

 const gp_Pnt2d& gp_Ax22d::Location () const
{ return point; }

 const gp_Dir2d& gp_Ax22d::XDirection () const
{ return vxdir; }

 const gp_Dir2d& gp_Ax22d::YDirection () const
{ return vydir; }

 void gp_Ax22d::Rotate (const gp_Pnt2d& P,
			      const double Ang)
{
  gp_Pnt2d Temp = point;
  Temp.Rotate (P,Ang);
  point = Temp;
  vxdir.Rotate (Ang);
  vydir.Rotate (Ang);
}

 gp_Ax22d gp_Ax22d::Rotated(const gp_Pnt2d& P,
				  const double Ang) const
{
  gp_Ax22d Temp = *this;
  Temp.Rotate (P,Ang);
  return Temp;
}

 void gp_Ax22d::Scale (const gp_Pnt2d& P, 
			     const double S)
{
  gp_Pnt2d Temp = point;
  Temp.Scale (P, S);
  point = Temp;
  if (S < 0.0) {
    vxdir.Reverse ();
    vydir.Reverse ();
  }
}

 gp_Ax22d gp_Ax22d::Scaled(const gp_Pnt2d& P, 
				 const double S) const 
{
  gp_Ax22d Temp = *this;
  Temp.Scale (P, S);
  return Temp;
}

 void gp_Ax22d::Transform (const gp_Trsf2d& T)
{
  gp_Pnt2d Temp = point;
  Temp.Transform (T);
  point = Temp;
  vxdir.Transform (T);
  vydir.Transform (T);
}

 gp_Ax22d gp_Ax22d::Transformed(const gp_Trsf2d& T) const
{
  gp_Ax22d Temp = *this;
  Temp.Transform (T);
  return Temp;
}

 void gp_Ax22d::Translate (const gp_Vec2d& V) 
{ point.Translate (V); }

 gp_Ax22d gp_Ax22d::Translated(const gp_Vec2d& V) const
{
  gp_Ax22d Temp = *this;
  Temp.Translate (V);
  return Temp;
}
 void gp_Ax22d::Translate (const gp_Pnt2d& P1,const gp_Pnt2d& P2)
{ point.Translate (P1, P2); }

 gp_Ax22d gp_Ax22d::Translated (const gp_Pnt2d& P1, 
				      const gp_Pnt2d& P2)  const
{
  gp_Ax22d Temp = *this;
  Temp.Translate (P1, P2);
  return Temp;
}

 void gp_Ax22d::Mirror (const gp_Pnt2d& P)
 {
	 gp_Pnt2d Temp = point;
	 Temp.Mirror (P);
	 point = Temp;
	 vxdir.Reverse ();
	 vydir.Reverse ();
 }

 gp_Ax22d gp_Ax22d::Mirrored(const gp_Pnt2d& P) const
 {
	 gp_Ax22d Temp = *this;
	 Temp.Mirror (P);
	 return Temp;
 }

 void gp_Ax22d::Mirror (const gp_Ax2d& A1)
 {
	 vydir.Mirror (A1);
	 vxdir.Mirror (A1);
	 gp_Pnt2d Temp = point;
	 Temp.Mirror (A1);
	 point = Temp;
 }

 gp_Ax22d gp_Ax22d::Mirrored(const gp_Ax2d& A1) const
 {
	 gp_Ax22d Temp = *this;
	 Temp.Mirror (A1);
	 return Temp;
 }

 bool gp_Ax2d::IsCoaxial (const gp_Ax2d& Other, 
	 const double AngularTolerance,
	 const double LinearTolerance) const
 {
	 gp_XY XY1 = loc.XY();
	 XY1.Subtract (Other.loc.XY());
	 double D1 = XY1.Crossed (Other.vdir.XY());
	 if (D1 < 0) D1 = - D1;
	 gp_XY XY2 = Other.loc.XY();
	 XY2.Subtract (loc.XY());
	 double D2 = XY2.Crossed (vdir.XY());
	 if (D2 < 0) D2 = - D2;
	 return (vdir.IsParallel (Other.vdir, AngularTolerance) &&
		 D1 <= LinearTolerance && D2 <= LinearTolerance);
 }

 void gp_Ax2d::Scale (const gp_Pnt2d& P,
	 const double S)
 {
	 loc.Scale(P, S);
	 if (S < 0.0)  vdir.Reverse();
 }

 void gp_Ax2d::Mirror (const gp_Pnt2d& P)
 {
	 loc.Mirror(P);
	 vdir.Reverse();
 }

 gp_Ax2d gp_Ax2d::Mirrored (const gp_Pnt2d& P) const
 {
	 gp_Ax2d A = *this;    
	 A.Mirror (P);
	 return A;
 }

 void gp_Ax2d::Mirror (const gp_Ax2d& A)
 {
	 loc.Mirror (A);
	 vdir.Mirror (A.vdir); 
 }

 gp_Ax2d gp_Ax2d::Mirrored (const gp_Ax2d& A) const
 {
	 gp_Ax2d AA = *this;
	 AA.Mirror (A);
	 return AA;
 }